import { CacheConfig, CacheItem } from '../types';

/**
 * 缓存管理器
 */
export class CacheManager<T> {
    /** 缓存配置 */
    private config: CacheConfig;
    /** 缓存数据 */
    private cache: Map<string, CacheItem<T>>;
    /** 缓存项总大小（字节） */
    private totalSize: number;

    /**
     * 构造函数
     * @param config 缓存配置
     */
    constructor(config: CacheConfig) {
        this.config = config;
        this.cache = new Map();
        this.totalSize = 0;
    }

    /**
     * 获取缓存项
     * @param key 缓存键
     */
    get(key: string): T | undefined {
        if (!this.config.enabled) {
            return undefined;
        }

        const item = this.cache.get(key);
        if (!item) {
            return undefined;
        }

        // 检查是否过期
        if (this.isExpired(item)) {
            this.delete(key);
            return undefined;
        }

        // 更新访问信息
        item.lastAccessTime = Date.now();
        item.accessCount++;

        return item.data;
    }

    /**
     * 设置缓存项
     * @param key 缓存键
     * @param data 缓存数据
     * @param size 数据大小（字节）
     */
    set(key: string, data: T, size: number): boolean {
        if (!this.config.enabled) {
            return false;
        }

        // 检查单个项大小限制
        if (size > this.config.maxItemSize) {
            return false;
        }

        // 如果已存在，先删除旧的
        if (this.cache.has(key)) {
            this.delete(key);
        }

        // 确保有足够空间
        while (this.totalSize + size > this.config.maxItemSize * this.config.maxEntries ||
               this.cache.size >= this.config.maxEntries) {
            this.evictOne();
        }

        const item: CacheItem<T> = {
            data,
            size,
            createTime: Date.now(),
            lastAccessTime: Date.now(),
            accessCount: 0
        };

        this.cache.set(key, item);
        this.totalSize += size;
        return true;
    }

    /**
     * 删除缓存项
     * @param key 缓存键
     */
    delete(key: string): void {
        const item = this.cache.get(key);
        if (item) {
            this.totalSize -= item.size;
            this.cache.delete(key);
        }
    }

    /**
     * 清空缓存
     */
    clear(): void {
        this.cache.clear();
        this.totalSize = 0;
    }

    /**
     * 获取缓存统计信息
     */
    getStats(): {
        totalEntries: number;
        totalSize: number;
        hitCount: number;
        missCount: number;
    } {
        let hitCount = 0;
        let missCount = 0;
        
        this.cache.forEach(item => {
            if (this.isExpired(item)) {
                missCount++;
            } else {
                hitCount++;
            }
        });

        return {
            totalEntries: this.cache.size,
            totalSize: this.totalSize,
            hitCount,
            missCount
        };
    }

    /**
     * 检查缓存项是否过期
     * @param item 缓存项
     */
    private isExpired(item: CacheItem<T>): boolean {
        return Date.now() - item.createTime > this.config.ttl;
    }

    /**
     * 驱逐一个缓存项
     * 使用LRU（最近最少使用）和访问频率相结合的策略
     */
    private evictOne(): void {
        let leastScore = Infinity;
        let leastKey: string | undefined;

        this.cache.forEach((item, key) => {
            // 计算综合评分（越低越应该被驱逐）
            // 考虑因素：最后访问时间、访问次数、数据大小
            const timeFactor = (Date.now() - item.lastAccessTime) / this.config.ttl;
            const accessFactor = 1 / (item.accessCount + 1);
            const sizeFactor = item.size / this.config.maxItemSize;
            const score = timeFactor * 0.4 + accessFactor * 0.4 + sizeFactor * 0.2;

            if (score < leastScore) {
                leastScore = score;
                leastKey = key;
            }
        });

        if (leastKey) {
            this.delete(leastKey);
        }
    }
}
